#include "thread_pool.h"
#include <shadow.h>
#include "sql_util.h"
#include "linked_list.h"


// wmx--6.19
// 跨文件使用全局的用户信息链表
extern ListNode *user_list;
extern MYSQL *mysql;

#define STR_LEN 8 //定义随机输出的字符串长度。

void userLoginCheckOne(task_t * task) {
    ListNode *node = user_list;
    while (node != NULL) {
        user_info_t *user = (user_info_t *)node->val;
        if (user->net_fd == task->peerfd) {

            // task的data是客户端传递过来的用户名
            memset(user->name, 0, sizeof(user->name));
            strcpy(user->name, task->data);
            // 查数据库有没有这个用户
            login_step_one(user);
            return ;
        }
        node = node->next;
    }
}
void userLoginCheckTwo(task_t * task) {
    ListNode *node = user_list;
    while (node != NULL) {
        user_info_t *user = (user_info_t *)node->val;
        if (user->net_fd == task->peerfd) {

            // task的data是客户端传递过来的密码    
            memset(user->encrypted, 0, sizeof(user->encrypted));
            strcpy(user->encrypted, task->data); 
            task->user=user;//此时 task->user有了用户名和密码和socket文件描述符
            login_step_two(user);
            return ;
        }
        node = node->next;
    }

}
void userRegisterOne(task_t * task) {
    srand(time(NULL));// 生成随机数时会用到
    ListNode *node = user_list;
    while (node != NULL) {
        user_info_t *user = (user_info_t *)node->val;
        if (user->net_fd == task->peerfd) {

            // task的data是客户端传递过来的用户名    
            memset(user->name, 0, sizeof(user->name));
            strcpy(user->name, task->data); 
            register_step_one(user);
            return ;
        }
        node = node->next;
    }

}
void userRegisterTwo(task_t * task) {
    ListNode *node = user_list;
    while (node != NULL) {
        user_info_t *user = (user_info_t *)node->val;
        if (user->net_fd == task->peerfd) {

            // task的data是客户端传递过来的密码    
            memset(user->encrypted, 0, sizeof(user->encrypted));
            strcpy(user->encrypted, task->data); 
            register_step_two(user);
            return ;
        }
        node = node->next;
    }

}



void get_setting(char *setting, char *cipher_text) {
    int i = 0;
    int j = 0;
    for(; cipher_text[i] && j != 3; ++i) {
        if (cipher_text[i] == '$') {
            ++j;
        }
    }
    memcpy(setting, cipher_text, i - 1);
}
// 如果用户在数据库中查询成功，那么用算法生成一个setting
// 给客户端，如果用户不存在，那么也发一个消息通知用户
void login_step_one(user_info_t *user) {

    train_t train;
    char result[256] = { 0 }; // 用于存储查询结果
    char query[512] = { 0 };
    sprintf(query, "SELECT username FROM users WHERE username = '%s';", user->name);

    // 查找数据库
    if (select_one(mysql, query, result) == 0) {
        if (strlen(result) > 0) {
            // 用户存在的情况, 从数据库中得到该用户的，发送setting给用户
            memset(&train, 0, sizeof(train));
            memset(query, 0, sizeof(query));
            memset(result, 0, sizeof(result));
            sprintf(query, "SELECT cryptpasswd FROM users WHERE username = '%s';", user->name);

            if (select_one(mysql, query, result) != 0) {
                WriteLog("Query failed\n");
            }

            char setting[512] = { 0 };
            get_setting(setting, result);

            train.len = strlen(setting);
            train.type = LOGIN_STEP_ONE_OK;
            memcpy(train.buff, setting, train.len);

            sendn(user->net_fd, &train, sizeof(int) + sizeof(int) + train.len);

        } else {
            // 用户不存在的情况，发一个第一个登录阶段失败标志，让用户注册
            memset(&train, 0, sizeof(train));
            train.len = 0;
            train.type = LOGIN_STEP_ONE_ERR;
            sendn(user->net_fd, &train, sizeof(int) + sizeof(int));
        }
    } else {
        // 空表也要注册
        // 用户不存在的情况，发一个第一个登录阶段失败标志，让用户注册
        memset(&train, 0, sizeof(train));
        train.len = 0;
        train.type = LOGIN_STEP_ONE_ERR;
        sendn(user->net_fd, &train, sizeof(int) + sizeof(int));
    }
}

// 登录验证阶段二，得到用户的密文，并比对
void login_step_two(user_info_t *user) {
    // 走到这里用户肯定存在，且密文在数据库里面
    train_t train;
    memset(&train, 0, sizeof(train));

    char result[256] = { 0 }; // 用于存储查询结果
    char query[512] = { 0 };
    sprintf(query, "SELECT cryptpasswd  FROM users WHERE username = '%s';", user->name);

    // 查找数据库
    if (select_one(mysql, query, result) == 0) {

        // 密码正确，把用户的pwd发送给客户端
        if (strcmp(user->encrypted, result) == 0) {

            // 设置用户登录状态
            user->login_status = LOGIN_IN;

            memset(query, 0, sizeof(query));
            memset(result, 0, sizeof(result));
            sprintf(query, "SELECT pwd  FROM users WHERE username = '%s';", user->name);
            if (select_one(mysql, query, result) != 0) {
                WriteLog("Query failed\n");
            }
            strcpy(user->pwd, result);

            train.type = LOGIN_STEP_TWO_OK;
            train.len = 0;
            sendn(user->net_fd, &train, sizeof(int) + sizeof(int));

            // 登录成功把当前信息传递给客户端
            curr_info_t curr;
            memset(&curr, 0, sizeof(curr_info_t));
            strcpy(curr.user_name, user->name);
            strcpy(curr.pwd, user->pwd);
            sendn(user->net_fd, &curr, sizeof(curr));

        }// 密码错误
        else {
            train.len = 0;
            train.type = LOGIN_STEP_TWO_ERR;
            sendn(user->net_fd, &train, sizeof(int) + sizeof(int));
        }

    } else {
        WriteLog("Query failed\n");
    }

}

void register_step_one(user_info_t *user) {

    // 查询用户是否已经存在如果存在不允许注册
    train_t train;
    memset(&train, 0, sizeof(train_t));
    char result[256] = { 0 }; // 用于存储查询结果
    char query[512] = { 0 };
    sprintf(query, "SELECT username FROM users WHERE username = '%s';", user->name);

    // 查找数据库
    if (select_one(mysql, query, result) == 0) {
        if (strlen(result) > 0) {
            // 用户存在的情况, 第一阶段注册失败，不允许注册，客户端直接退出
            train.len = 0;
            train.type = REGISTER_STEP_ONE_ERR;
            sendn(user->net_fd, &train, sizeof(int) + sizeof(int));
            return ;
        }

        // 用户不存在，发一个setting给客户端
        char str[STR_LEN + 1] = {0}; // 用静态变量确保返回值有效
        int i, flag;
        for (i = 0; i < STR_LEN; i++) {
            flag = rand() % 3;
            switch (flag) {
            case 0: str[i] = rand() % 26 + 'a'; break;
            case 1: str[i] = rand() % 26 + 'A'; break;
            case 2: str[i] = rand() % 10 + '0'; break;
            }
        }
        str[STR_LEN] = '\0'; // 确保字符串以空字符结尾

        char setting[512] = { 0 };
        sprintf(setting, "$6$%s$", str);
        // 把setting发送给客户端

        memset(&train, 0, sizeof(train_t));
        train.len = strlen(setting);
        train.type = REGISTER_STEP_ONE;
        memcpy(train.buff, setting, train.len);

        sendn(user->net_fd, &train, sizeof(int) + sizeof(int) + train.len);
    }
    else {
        // 空表也是用户不存在
        // 用户不存在，发一个setting给客户端
        char str[STR_LEN + 1] = {0}; // 用静态变量确保返回值有效
        int i, flag;
        for (i = 0; i < STR_LEN; i++) {
            flag = rand() % 3;
            switch (flag) {
            case 0: str[i] = rand() % 26 + 'a'; break;
            case 1: str[i] = rand() % 26 + 'A'; break;
            case 2: str[i] = rand() % 10 + '0'; break;
            }
        }
        str[STR_LEN] = '\0'; // 确保字符串以空字符结尾

        char setting[512] = { 0 };
        sprintf(setting, "$6$%s$", str);
        // 把setting发送给客户端

        memset(&train, 0, sizeof(train_t));
        train.len = strlen(setting);
        train.type = REGISTER_STEP_ONE;
        memcpy(train.buff, setting, train.len);

        sendn(user->net_fd, &train, sizeof(int) + sizeof(int) + train.len);

    }
}

void register_step_two(user_info_t *user) {
    // 写数据库
    char query[512] = { 0 };
    sprintf(query, "INSERT INTO users (username, cryptpasswd, pwd) VALUES ('%s', '%s', '%s');", user->name, user->encrypted, user->name);
    // printf("%s\n", query);

    // 执行sql语句完成注册
    sql_execute(mysql, query);

    // 查找这个用户的ID，注册虚拟文件表
    char result[1024] = { 0 };
    memset(query, 0, sizeof(query));
    snprintf(query,  sizeof(query), "select id  from users where username = '%s';", user->name);

    // 上面插入了，这里肯定执行成功
    select_one(mysql, query, result);
    int id = atoi(result);
    memset(query, 0, sizeof(query));
    snprintf(query, sizeof(query), "INSERT INTO virtual_files (parent_id, filename, owner_id, md5, filesize, type) VALUES ('0', '%s', '%d', '0', '0', 'd');", user->name, id);
    sql_execute(mysql, query);
}
